package com.sghj.construction.controller;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sghj.config.ReturnResult;
import com.sghj.config.handler.ResultCode;
import com.sghj.config.handler.exceptionHandler.MyException;
import com.sghj.config.redis.QueuingPoll;
import com.sghj.construction.entity.ConstructionSitePlan;
import com.sghj.construction.entity.PlanQuery;
import com.sghj.construction.entity.dto.CallRecordJsonDTO;
import com.sghj.construction.entity.vo.ConstructionSitePlanVo;
import com.sghj.construction.mapper.ConstructionSitePlanMapper;
import com.sghj.construction.service.ConstructionSitePlanService;
import com.sghj.record.entity.RecordOutcall;
import com.sghj.record.mapper.RecordIncallMapper;
import com.sghj.record.mapper.RecordOutcallMapper;
import com.sghj.record.service.RecordIncallService;
import com.sghj.record.service.RecordOutcallService;
import com.sghj.utils.HttpUtils;
import com.sghj.utils.MD5;
import com.sghj.utils.MD5Utils;
import com.sghj.utils.excel.ExcelUtils;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Random;

@RestController
@RequestMapping("/construction")
public class ConstructionSitePlanController {

    @Autowired
    private ConstructionSitePlanService planService;

    @Resource
    private RecordIncallService recordIncallService;

    @Resource
    private RecordOutcallService recordOutcallService;

    @Resource
    private ConstructionSitePlanMapper constructionSitePlanMapper;

    @Resource
    private RecordOutcallMapper recordOutcallMapper;

    @Resource
    private RecordIncallMapper recordIncallMapper;

    //    final String ip = "http://localhost:";
    final String ip = "http://100.1.7.94:";


    //增加施工计划
    @QueuingPoll
    @PostMapping("/addPlan")
    public ReturnResult addPlan(@RequestBody ConstructionSitePlan sitePlan) {
        if (sitePlan == null) {
            return ReturnResult.failed().message("请输入参数");
        }
        ConstructionSitePlan sitePlanOne = planService.selectByDayPlan(sitePlan.getDayPlanNumber());
        if (sitePlanOne != null) {
            return ReturnResult.failed().message("已添加计划，请勿重新添加！");
        }
        int num = planService.insertConstruction(sitePlan);
        if (num > 0) {
            return ReturnResult.success().message("施工计划添加成功");
        }
        return ReturnResult.failed().message("施工计划添加失败");
    }

    //删除施工计划
    @PostMapping("/deletePlan")
    public ReturnResult deletePlan(@RequestBody ConstructionSitePlan sitePlan) {
        if (sitePlan.getConstructionSiteId() == 0) {
            return ReturnResult.failed().message("参数为空");
        }
        sitePlan.setIsDelete(1);
        int num = planService.deleteConstructionById(sitePlan.getConstructionSiteId());
        if (num > 0) {
            return ReturnResult.success().message("删除成功");
        }
        return ReturnResult.failed().message("删除失败");
    }

    //修改施工计划(ID)
    @PostMapping("/updatePlan")
    public ReturnResult updatePlan(@RequestBody ConstructionSitePlan sitePlan) {
        if (sitePlan == null || sitePlan.getConstructionSiteId() == 0) {
            return ReturnResult.failed().message("参数为空");
        }
        Integer haveNum = planService.selectNumByDayPlan(sitePlan.getDayPlanNumber(), sitePlan.getConstructionSiteId());
        if (haveNum > 0) {
            return ReturnResult.failed().message("已添加计划！");
        }
        sitePlan.setUpdateTime(new Date());
        int num = planService.updateConstructionById(sitePlan);
        if (num > 0) {
            return ReturnResult.success().message("修改成功");
        }
        return ReturnResult.success().message("修改失败");
    }

    //修改施工计划(计划号)
    @PostMapping("/updateDayPlan")
    public ReturnResult updateDayPlan(@RequestBody ConstructionSitePlan sitePlan) {
        if (sitePlan == null || sitePlan.getDayPlanNumber() == 0) {
            return ReturnResult.failed().message("参数为空");
        }
        int num = planService.updateConstructionByDayPlan(sitePlan);
        if (num > 0) {
            return ReturnResult.success().message("修改成功");
        }
        return ReturnResult.success().message("修改失败");
    }

    /*
     * 拨打电话
     * */
    @PostMapping("callingPerson")
    public void callingPerson() {

        System.out.println("执行一次");
        // 实现你的接口调用逻辑
        List<ConstructionSitePlan> listPlan = planService.selectCallInfo();

        System.out.println("队列数量为:" + listPlan.size());

        if (listPlan.size() > 0) {

            Random random = new Random();
            int randomIndex = random.nextInt(listPlan.size()); // 生成一个随机的索引

            //选取最先的记录执行拨打电话操作
            ConstructionSitePlan callingPlan = listPlan.get(randomIndex);

            long differenceInMillis = callingPlan.getEndTime().getTime() - callingPlan.getStartTime().getTime();
            long differenceInMinutes = differenceInMillis / (1000 * 60);

            try {
                //初始化部分参数
                StringBuilder startCalling = new StringBuilder();
                String startCallingRes = "";
                StringBuilder checkCalling = new StringBuilder();
                String checkCallingRes = "";

                RecordOutcall recordOutcall = new RecordOutcall();

                // 定义日期格式
                SimpleDateFormat sdf = new SimpleDateFormat("MM月dd日HH时mm分");

                // 定义需要替换的标点符号
                String punctuationRegex = "[、，。！？《》（）【】「」『』{}<>#*()]";

                /*
                 *
                 * 第一步
                 * 调用拨打电话接口
                 *
                 * */
                //创建接口地址参数
                startCalling = startCalling.append(ip + "88/autodailtask.ashx?");//接口地址
                startCalling = startCalling.append("enterid=1453&");//enterid参数
                startCalling = startCalling.append("logname=AF26231585&");//logname参数
                startCalling = startCalling.append("dialtype=4&");//dialtype参数
                startCalling = startCalling.append("phone=").append(callingPlan.getMonitoringPhone()).append("&");//phone参数
                startCalling = startCalling.append("words=");//words参数
                startCalling = startCalling.append("尊敬的施工盯控人员" + fixString(callingPlan.getMonitoringPersonnel()) + "您好,");//words参数
                startCalling = startCalling.append("您于" + sdf.format(callingPlan.getStartTime()) + "至" + sdf.format(callingPlan.getEndTime()) + "的,");//words参数
                startCalling = startCalling.append("位于" + fixString(callingPlan.getLocationPlace()) + "的" + fixString(callingPlan.getConstructionSiteName()) + "即将开始,");//words参数
                startCalling = startCalling.append("施工日计划号为" + callingPlan.getDayPlanNumber() + ",");//words参数
                startCalling = startCalling.append("施工计划时长" + differenceInMinutes + "分钟,距离施工开始时间已小于2小时,请尽快前往施工现场,");//words参数
                startCalling = startCalling.append("确认请按1号键,已委托他人请按2号键&");//words参数
                startCalling = startCalling.append("datatype=json&playtimes=3");

                System.out.println("请求的参数是：" + startCalling.toString());

                startCallingRes = HttpUtils.sendGETRequest(startCalling.toString());

                System.out.println("拨打电话的结果是：" + startCallingRes);

                //将拨打电话结果转换
                if (startCallingRes.length() >= 2) {

                    startCallingRes = startCallingRes.substring(1, startCallingRes.length() - 1);


                    //等待5分钟之后执行剩余部分
                    Thread.sleep(300000); // 5分钟等待

                    try {
                        JSONObject callingJsonResult = new JSONObject();
                        callingJsonResult = JSONObject.parseObject(startCallingRes);

                        if (callingJsonResult.getString("taskdetailid") != null) {
                            /*
                             *
                             * 第二步
                             * 调用查询拨打电话结果接口
                             *
                             * */
                            System.out.println("调用第二个接口");

                            /*调用拨打电话结果查询接口*/
                            //创建接口地址参数
                            checkCalling = checkCalling.append(ip + "88/handle/call_record.ashx?");//接口地址
                            checkCalling = checkCalling.append("TaskDetailID=").append(callingJsonResult.getString("taskdetailid"));//TaskDetailID参数

                            checkCallingRes = HttpUtils.sendGETRequest(checkCalling.toString());

                            int retryCount = 0;
                            while (retryCount < 5) { // 最多重试5次
                                if (checkCallingRes.length() > 2) {
                                    System.out.println("第" + retryCount + "次查询结果是" + checkCallingRes);
                                    checkCallingRes = checkCallingRes.substring(1, checkCallingRes.length() - 1);
                                    checkCallingRes = checkCallingRes.replace("\\", "");

                                    // 将查询打电话的结果进行转化
                                    JSONObject checkJsonResult = new JSONObject();
                                    checkJsonResult = JSONObject.parseObject(checkCallingRes);

                                    try {
                                        if (checkJsonResult.getString("SelectKey") != null) {
                                            checkCallingRes = checkJsonResult.getString("SelectKey");
                                        } else {
                                            checkCallingRes = "";
                                        }
                                    } catch (Exception e) {
                                        throw new MyException(ResultCode.FAIL, "获取通话结果失败");
                                    }

                                    recordOutcall.setDayPlanNumber(callingPlan.getDayPlanNumber());
                                    recordOutcall.setCallId(callingJsonResult.getString("taskdetailid"));
                                    recordOutcall.setIsDelete(0);
                                    recordOutcall.setCreateTime(new Date());
                                    recordOutcall.setUpdateTime(new Date());

                                    /* 根据拨打电话结果进行记录修改 */
                                    switch (checkCallingRes) {
                                        case "1":
                                            recordOutcall.setCallResult("1");
                                            recordOutcallMapper.insert(recordOutcall);
                                            callingPlan.setCallStatus(1);
                                            constructionSitePlanMapper.updateById(callingPlan);
                                            break;
                                        case "2":
                                            recordOutcall.setCallResult("2");
                                            recordOutcallMapper.insert(recordOutcall);
                                            callingPlan.setCallStatus(2);
                                            constructionSitePlanMapper.updateById(callingPlan);
                                            break;
                                        default:
                                            recordOutcall.setCallResult("3");
                                            recordOutcallMapper.insert(recordOutcall);
                                            callingPlan.setCallStatus(0);
                                            constructionSitePlanMapper.updateById(callingPlan);
                                            break;
                                    }
                                    break; // 执行成功则退出循环
                                } else {
                                    retryCount++;
                                    if (retryCount < 5) {
                                        try {
                                            Thread.sleep(10000); // 等待10秒
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                    } else {
                                        // 达到最大重试次数仍然不满足条件，结束循环
                                        recordOutcall.setCallResult("0");
                                        recordOutcall.setDayPlanNumber(callingPlan.getDayPlanNumber());
                                        recordOutcall.setCallId(callingJsonResult.getString("taskdetailid"));
                                        recordOutcall.setIsDelete(0);
                                        recordOutcall.setCreateTime(new Date());
                                        recordOutcall.setUpdateTime(new Date());
                                        recordOutcallMapper.insert(recordOutcall);

                                        //查询当前计划共拨打电话的次数
                                        int callNum = recordOutcallMapper.selectNumByDayPlanNumber(callingPlan.getDayPlanNumber());
                                        if (callNum >= 3) {
                                            callingPlan.setCallStatus(3);
                                            constructionSitePlanMapper.updateById(callingPlan);
                                        }
                                        break;
                                    }
                                }
                            }

                        } else {
                            System.out.println("拨打电话失败");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
//                        Thread.sleep(20000); // 3分钟等待
                        System.out.println("拨打电话失败");
                    }


                }

            } catch (Exception e) {
                e.printStackTrace();
                throw new MyException(ResultCode.FAIL, "拨打电话失败");
            }
        }
    }

    /*
     * 查询回拨结果
     * */
    @PostMapping("checkInCallRecord")
    public void checkInCallRecord() {
        System.out.println("调用了查询接口");
        /* 1.调用获取通话记录接口*/

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
//        now = now.minus(Duration.ofMinutes(1));

        // 计算当前时间前20分钟的时间
        LocalDateTime timeAgo = now.minus(Duration.ofMinutes(20));

        // 将 LocalDateTime 转换为 Date
        Date currentDate = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());//当前时间
        Date timeAgoDate = Date.from(timeAgo.atZone(ZoneId.systemDefault()).toInstant());//十分钟之前

        StringBuilder keyParams = new StringBuilder();
        StringBuilder getInCallParams = new StringBuilder();
        String key = null;

        //获取请求接口所需秘钥
        keyParams.append("appid=AF26231585&calltype=1&charset=UTF_8&");
        keyParams.append("endcalltime=" + sdf.format(currentDate) + "&");//拼接查询截止时间
        keyParams.append("enterid=1453&methodname=CallRecord&");
        keyParams.append("startcalltime=" + sdf.format(timeAgoDate) + "&");//拼接查询起始时间
        keyParams.append("timestamp=" + sdf.format(currentDate) + "&");//拼接时间戳
        keyParams.append("version=1.0&key=zfXAhqWhoBD");



        key = MD5Utils.encrypt(keyParams.toString());

        getInCallParams.append("{\"version\":\"1.0\"," +
                "\"charset\": \"UTF_8\"," +
                "\"timestamp\": \"" + sdf.format(currentDate) + "\"," +
                "\"enterid\": \"1453\"," +
                "\"appid\": \"AF26231585\"," +
                "\"calltype\": \"1\"," +
                "\"startcalltime\": \"" + sdf.format(timeAgoDate) + "\"," +
                "\"endcalltime\": \"" + sdf.format(currentDate) + "\"," +
                "\"sign\": \"" + key + "\"}");

        System.out.println("请求参数为："+ getInCallParams.toString());

        try {
            String sendRes = HttpUtils.sendPOSTRequest(ip + "8083/SvrCall.ashx?MethodName=CallRecord", getInCallParams.toString());
            System.out.println("查询结果是:" + sendRes);

            //处理查询的结果
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 解析 JSON
                JsonNode rootNode = objectMapper.readTree(sendRes);
                JsonNode dataNode = rootNode.path("data");
                List<CallRecordJsonDTO> callRecordList = objectMapper.readValue(dataNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, CallRecordJsonDTO.class));

                /* 2.遍历全部查询到的通话记录，并对每条记录进行处理*/
                for (CallRecordJsonDTO record : callRecordList) {
//                    System.out.println(record.toString());
                    // 进行结果处理

                    /*a.判断是否有按键信息*/
                    if (record.getRecordkey().contains(",")) {
                        Integer planId, selectKey;
                        String callNo, phoneNumber;
                        planId = Integer.valueOf(record.getRecordkey().split(",")[0]);
                        selectKey = Integer.valueOf(record.getRecordkey().split(",")[1]);
                        phoneNumber = record.getCallno();
                        callNo = record.getId();

                        recordIncallService.insertInCallRecord(callNo, planId, selectKey, phoneNumber, sdf.parse(record.getCalltime()));
                    } else {
                        continue;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    /*
     * 将逾期未回拨记录回拨状态置为已逾期
     * */
    @PostMapping("updateNotCallBackRecord")
    public void updateNotCallBackRecord() {
        int updateRes = planService.updateNotCallBackRecord();
    }


    /**
     * 查询计划信息（分页）
     */
    @PostMapping("searchPlanPage")
    public ReturnResult searchPlan(@RequestBody(required = false) PlanQuery query) {
        if (query == null || query.getCurrent() == null || query.getLimit() == null) {
            return ReturnResult.failed().message("参数为空");
        }
        //创建分页
        Page<ConstructionSitePlanVo> page = new Page<>(query.getCurrent(), query.getLimit());
        IPage<ConstructionSitePlanVo> numPage = planService.selectByInfo(query, page);
        return ReturnResult.success().data("list", numPage.getRecords()).data("total", numPage.getTotal()).message("查询成功");
    }

    /**
     * 导出计划信息
     */
    @PostMapping("exportPlan")
    @ApiOperation(value = "导出计划信息")
    public void exportPlan(HttpServletResponse response, @RequestBody PlanQuery query) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss");
        //进行记录查询
        List<ConstructionSitePlanVo> planList = planService.searchPlanList(query);
        String sheetName = "施工日计划盯控人员外呼系统明细表" + sdf1.format(new Date());
        String[] title = {"序号", "日计划号", "线别", "地点", "施工项目", "施工开始时间", "施工截止时间", "盯控人", "盯控人电话", "外呼状态", "外呼时间", "回电电话", "回电状态", "回电时间"};
        ExcelUtils.exportPlan(response, sheetName, planList, query, title);
    }


    private String fixString(String stringBefore) {
        String punctuationRegex = "[、，。！？《》（）【】「」『』{}<>()]";

        stringBefore = stringBefore.replaceAll(punctuationRegex, ",").replaceAll("\\s+", "");

        stringBefore = stringBefore.replaceAll("#", "井");
        stringBefore = stringBefore.replaceAll("\\*", "星");

        return stringBefore;
    }
}
